<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>

<meta charset="utf-8">
<meta name="generator" content="quarto-1.7.33">

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">


<title>3&nbsp; Memory and Allocators – Introduction to Zig</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
  width: 0.8em;
  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
  vertical-align: middle;
}
/* CSS for syntax highlighting */
html { -webkit-text-size-adjust: 100%; }
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
  }
pre.numberSource { margin-left: 3em;  padding-left: 4px; }
div.sourceCode
  {   }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
/* CSS for citations */
div.csl-bib-body { }
div.csl-entry {
  clear: both;
  margin-bottom: 0em;
}
.hanging-indent div.csl-entry {
  margin-left:2em;
  text-indent:-2em;
}
div.csl-left-margin {
  min-width:2em;
  float:left;
}
div.csl-right-inline {
  margin-left:2em;
  padding-left:1em;
}
div.csl-indent {
  margin-left: 2em;
}</style>


<script src="../site_libs/quarto-nav/quarto-nav.js"></script>
<script src="../site_libs/quarto-nav/headroom.min.js"></script>
<script src="../site_libs/clipboard/clipboard.min.js"></script>
<script src="../site_libs/quarto-search/autocomplete.umd.js"></script>
<script src="../site_libs/quarto-search/fuse.min.js"></script>
<script src="../site_libs/quarto-search/quarto-search.js"></script>
<meta name="quarto:offset" content="../">
<link href="../Chapters/01-base64.html" rel="next">
<link href="../Chapters/03-structs.html" rel="prev">
<script src="../site_libs/quarto-html/quarto.js" type="module"></script>
<script src="../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
<script src="../site_libs/quarto-html/popper.min.js"></script>
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
<script src="../site_libs/quarto-html/anchor.min.js"></script>
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-59898bd1c6b9d2bb783127feaa000c76.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-dark-d329e753491efaeac79c98c4b193a686.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-59898bd1c6b9d2bb783127feaa000c76.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="../site_libs/bootstrap/bootstrap-5a7d69291c2a8c67bc3a157f4354e263.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
<link href="../site_libs/bootstrap/bootstrap-dark-a459d9a911ec262923466a12d18bc01e.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
<link href="../site_libs/bootstrap/bootstrap-5a7d69291c2a8c67bc3a157f4354e263.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
<script id="quarto-search-options" type="application/json">{
  "location": "sidebar",
  "copy-button": false,
  "collapse-after": 3,
  "panel-placement": "start",
  "type": "textbox",
  "limit": 50,
  "keyboard-shortcut": [
    "f",
    "/",
    "s"
  ],
  "show-item-context": false,
  "language": {
    "search-no-results-text": "No results",
    "search-matching-documents-text": "matching documents",
    "search-copy-link-title": "Copy link to search",
    "search-hide-matches-text": "Hide additional matches",
    "search-more-match-text": "more match in this document",
    "search-more-matches-text": "more matches in this document",
    "search-clear-button-title": "Clear",
    "search-text-placeholder": "",
    "search-detached-cancel-button-title": "Cancel",
    "search-submit-button-title": "Submit",
    "search-label": "Search"
  }
}</script>
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-6CHJXK4CEV"></script>

<script type="text/javascript">

window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-6CHJXK4CEV', { 'anonymize_ip': true});
</script>


</head>

<body class="nav-sidebar floating quarto-light"><script id="quarto-html-before-body" type="application/javascript">
    const toggleBodyColorMode = (bsSheetEl) => {
      const mode = bsSheetEl.getAttribute("data-mode");
      const bodyEl = window.document.querySelector("body");
      if (mode === "dark") {
        bodyEl.classList.add("quarto-dark");
        bodyEl.classList.remove("quarto-light");
      } else {
        bodyEl.classList.add("quarto-light");
        bodyEl.classList.remove("quarto-dark");
      }
    }
    const toggleBodyColorPrimary = () => {
      const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
      if (bsSheetEl) {
        toggleBodyColorMode(bsSheetEl);
      }
    }
    const setColorSchemeToggle = (alternate) => {
      const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
      for (let i=0; i < toggles.length; i++) {
        const toggle = toggles[i];
        if (toggle) {
          if (alternate) {
            toggle.classList.add("alternate");
          } else {
            toggle.classList.remove("alternate");
          }
        }
      }
    };
    const toggleColorMode = (alternate) => {
      // Switch the stylesheets
      const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
      const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
      manageTransitions('#quarto-margin-sidebar .nav-link', false);
      if (alternate) {
        // note: dark is layered on light, we don't disable primary!
        enableStylesheet(alternateStylesheets);
        for (const sheetNode of alternateStylesheets) {
          if (sheetNode.id === "quarto-bootstrap") {
            toggleBodyColorMode(sheetNode);
          }
        }
      } else {
        disableStylesheet(alternateStylesheets);
        enableStylesheet(primaryStylesheets)
        toggleBodyColorPrimary();
      }
      manageTransitions('#quarto-margin-sidebar .nav-link', true);
      // Switch the toggles
      setColorSchemeToggle(alternate)
      // Hack to workaround the fact that safari doesn't
      // properly recolor the scrollbar when toggling (#1455)
      if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
        manageTransitions("body", false);
        window.scrollTo(0, 1);
        setTimeout(() => {
          window.scrollTo(0, 0);
          manageTransitions("body", true);
        }, 40);
      }
    }
    const disableStylesheet = (stylesheets) => {
      for (let i=0; i < stylesheets.length; i++) {
        const stylesheet = stylesheets[i];
        stylesheet.rel = 'disabled-stylesheet';
      }
    }
    const enableStylesheet = (stylesheets) => {
      for (let i=0; i < stylesheets.length; i++) {
        const stylesheet = stylesheets[i];
        if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
          stylesheet.rel = 'stylesheet';
        }
      }
    }
    const manageTransitions = (selector, allowTransitions) => {
      const els = window.document.querySelectorAll(selector);
      for (let i=0; i < els.length; i++) {
        const el = els[i];
        if (allowTransitions) {
          el.classList.remove('notransition');
        } else {
          el.classList.add('notransition');
        }
      }
    }
    const isFileUrl = () => {
      return window.location.protocol === 'file:';
    }
    const hasAlternateSentinel = () => {
      let styleSentinel = getColorSchemeSentinel();
      if (styleSentinel !== null) {
        return styleSentinel === "alternate";
      } else {
        return false;
      }
    }
    const setStyleSentinel = (alternate) => {
      const value = alternate ? "alternate" : "default";
      if (!isFileUrl()) {
        window.localStorage.setItem("quarto-color-scheme", value);
      } else {
        localAlternateSentinel = value;
      }
    }
    const getColorSchemeSentinel = () => {
      if (!isFileUrl()) {
        const storageValue = window.localStorage.getItem("quarto-color-scheme");
        return storageValue != null ? storageValue : localAlternateSentinel;
      } else {
        return localAlternateSentinel;
      }
    }
    const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
      const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
      const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
      let newTheme = '';
      if(authorPrefersDark) {
        newTheme = isAlternate ? baseTheme : alternateTheme;
      } else {
        newTheme = isAlternate ? alternateTheme : baseTheme;
      }
      const changeGiscusTheme = () => {
        // From: https://github.com/giscus/giscus/issues/336
        const sendMessage = (message) => {
          const iframe = document.querySelector('iframe.giscus-frame');
          if (!iframe) return;
          iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
        }
        sendMessage({
          setConfig: {
            theme: newTheme
          }
        });
      }
      const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
      if (isGiscussLoaded) {
        changeGiscusTheme();
      }
    };
    const authorPrefersDark = false;
    const darkModeDefault = authorPrefersDark;
      document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
      document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
    let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
    // Dark / light mode switch
    window.quartoToggleColorScheme = () => {
      // Read the current dark / light value
      let toAlternate = !hasAlternateSentinel();
      toggleColorMode(toAlternate);
      setStyleSentinel(toAlternate);
      toggleGiscusIfUsed(toAlternate, darkModeDefault);
      window.dispatchEvent(new Event('resize'));
    };
    // Switch to dark mode if need be
    if (hasAlternateSentinel()) {
      toggleColorMode(true);
    } else {
      toggleColorMode(false);
    }
  </script>

<div id="quarto-search-results"></div>
  <header id="quarto-header" class="headroom fixed-top">
  <nav class="quarto-secondary-nav">
    <div class="container-fluid d-flex">
      <button type="button" class="quarto-btn-toggle btn" data-bs-toggle="collapse" role="button" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
        <i class="bi bi-layout-text-sidebar-reverse"></i>
      </button>
        <nav class="quarto-page-breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="../Chapters/01-memory.html"><span class="chapter-number">3</span>&nbsp; <span class="chapter-title">Memory and Allocators</span></a></li></ol></nav>
        <a class="flex-grow-1" role="navigation" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">      
        </a>
      <button type="button" class="btn quarto-search-button" aria-label="Search" onclick="window.quartoOpenSearch();">
        <i class="bi bi-search"></i>
      </button>
    </div>
  </nav>
</header>
<!-- content -->
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
<!-- sidebar -->
  <nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation floating overflow-auto">
    <div class="pt-lg-2 mt-2 text-left sidebar-header">
    <div class="sidebar-title mb-0 py-0">
      <a href="../">Introduction to Zig</a> 
        <div class="sidebar-tools-main">
  <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool  px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
</div>
    </div>
      </div>
        <div class="mt-2 flex-shrink-0 align-items-center">
        <div class="sidebar-search">
        <div id="quarto-search" class="" title="Search"></div>
        </div>
        </div>
    <div class="sidebar-menu-container"> 
    <ul class="list-unstyled mt-1">
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../index.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text">Welcome</span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-zig-weird.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">1</span>&nbsp; <span class="chapter-title">Introducing Zig</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/03-structs.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">2</span>&nbsp; <span class="chapter-title">Control flow, structs, modules and types</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-memory.html" class="sidebar-item-text sidebar-link active">
 <span class="menu-text"><span class="chapter-number">3</span>&nbsp; <span class="chapter-title">Memory and Allocators</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-base64.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">4</span>&nbsp; <span class="chapter-title">Project 1 - Building a base64 encoder/decoder</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/02-debugging.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">5</span>&nbsp; <span class="chapter-title">Debugging Zig applications</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/05-pointers.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">6</span>&nbsp; <span class="chapter-title">Pointers and Optionals</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/04-http-server.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">7</span>&nbsp; <span class="chapter-title">Project 2 - Building a HTTP Server from scratch</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/03-unittests.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">8</span>&nbsp; <span class="chapter-title">Unit tests</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/07-build-system.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">9</span>&nbsp; <span class="chapter-title">Build System</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/09-error-handling.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">10</span>&nbsp; <span class="chapter-title">Error handling and unions</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/09-data-structures.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">11</span>&nbsp; <span class="chapter-title">Data Structures</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/10-stack-project.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">12</span>&nbsp; <span class="chapter-title">Project 3 - Building a stack data structure</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/12-file-op.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">13</span>&nbsp; <span class="chapter-title">Filesystem and Input/Output (IO)</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/14-zig-c-interop.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">14</span>&nbsp; <span class="chapter-title">Zig interoperability with C</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/13-image-filter.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">15</span>&nbsp; <span class="chapter-title">Project 4 - Developing an image filter</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/14-threads.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">16</span>&nbsp; <span class="chapter-title">Introducing threads and parallelism in Zig</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/15-vectors.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">17</span>&nbsp; <span class="chapter-title">Introducing Vectors and SIMD</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/references.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text">References</span></a>
  </div>
</li>
    </ul>
    </div>
</nav>
<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div>
<!-- margin-sidebar -->
    <div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
        <nav id="TOC" role="doc-toc" class="toc-active">
    <h2 id="toc-title">Table of contents</h2>
   
  <ul>
  <li><a href="#memory-spaces" id="toc-memory-spaces" class="nav-link active" data-scroll-target="#memory-spaces"><span class="header-section-number">3.1</span> Memory spaces</a>
  <ul class="collapse">
  <li><a href="#sec-compile-time" id="toc-sec-compile-time" class="nav-link" data-scroll-target="#sec-compile-time"><span class="header-section-number">3.1.1</span> Compile-time known versus runtime known</a></li>
  <li><a href="#global-data-register" id="toc-global-data-register" class="nav-link" data-scroll-target="#global-data-register"><span class="header-section-number">3.1.2</span> Global data register</a></li>
  <li><a href="#stack-vs-heap" id="toc-stack-vs-heap" class="nav-link" data-scroll-target="#stack-vs-heap"><span class="header-section-number">3.1.3</span> Stack vs Heap</a></li>
  <li><a href="#sec-stack" id="toc-sec-stack" class="nav-link" data-scroll-target="#sec-stack"><span class="header-section-number">3.1.4</span> Stack</a></li>
  <li><a href="#sec-heap" id="toc-sec-heap" class="nav-link" data-scroll-target="#sec-heap"><span class="header-section-number">3.1.5</span> Heap</a></li>
  <li><a href="#summary" id="toc-summary" class="nav-link" data-scroll-target="#summary"><span class="header-section-number">3.1.6</span> Summary</a></li>
  </ul></li>
  <li><a href="#sec-stack-overflow" id="toc-sec-stack-overflow" class="nav-link" data-scroll-target="#sec-stack-overflow"><span class="header-section-number">3.2</span> Stack overflows</a></li>
  <li><a href="#sec-allocators" id="toc-sec-allocators" class="nav-link" data-scroll-target="#sec-allocators"><span class="header-section-number">3.3</span> Allocators</a>
  <ul class="collapse">
  <li><a href="#what-are-allocators" id="toc-what-are-allocators" class="nav-link" data-scroll-target="#what-are-allocators"><span class="header-section-number">3.3.1</span> What are allocators?</a></li>
  <li><a href="#why-you-need-an-allocator" id="toc-why-you-need-an-allocator" class="nav-link" data-scroll-target="#why-you-need-an-allocator"><span class="header-section-number">3.3.2</span> Why you need an allocator?</a></li>
  <li><a href="#the-different-types-of-allocators" id="toc-the-different-types-of-allocators" class="nav-link" data-scroll-target="#the-different-types-of-allocators"><span class="header-section-number">3.3.3</span> The different types of allocators</a></li>
  <li><a href="#general-purpose-allocators" id="toc-general-purpose-allocators" class="nav-link" data-scroll-target="#general-purpose-allocators"><span class="header-section-number">3.3.4</span> General-purpose allocators</a></li>
  <li><a href="#page-allocator" id="toc-page-allocator" class="nav-link" data-scroll-target="#page-allocator"><span class="header-section-number">3.3.5</span> Page allocator</a></li>
  <li><a href="#buffer-allocators" id="toc-buffer-allocators" class="nav-link" data-scroll-target="#buffer-allocators"><span class="header-section-number">3.3.6</span> Buffer allocators</a></li>
  <li><a href="#sec-arena-allocator" id="toc-sec-arena-allocator" class="nav-link" data-scroll-target="#sec-arena-allocator"><span class="header-section-number">3.3.7</span> Arena allocator</a></li>
  <li><a href="#the-alloc-and-free-methods" id="toc-the-alloc-and-free-methods" class="nav-link" data-scroll-target="#the-alloc-and-free-methods"><span class="header-section-number">3.3.8</span> The <code>alloc()</code> and <code>free()</code> methods</a></li>
  <li><a href="#the-create-and-destroy-methods" id="toc-the-create-and-destroy-methods" class="nav-link" data-scroll-target="#the-create-and-destroy-methods"><span class="header-section-number">3.3.9</span> The <code>create()</code> and <code>destroy()</code> methods</a></li>
  </ul></li>
  </ul>
</nav>
    </div>
<!-- main -->
<main class="content" id="quarto-document-content">


<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title"><span id="sec-memory-chap" class="quarto-section-identifier"><span class="chapter-number">3</span>&nbsp; <span class="chapter-title">Memory and Allocators</span></span></h1>
</div>



<div class="quarto-title-meta">

    
  
    
  </div>
  


</header>


<p>In this chapter, we will talk about memory. How does Zig control memory? What common tools are used? Are there any important aspects that make memory different/special in Zig? You will find the answers here.</p>
<p>Computers fundamentally rely on memory to function. This memory acts as a temporary storage space for the data and values generated during computations. Without memory, the core concepts of “variables” and “objects” in programming languages would be impossible.</p>
<section id="memory-spaces" class="level2" data-number="3.1">
<h2 data-number="3.1" class="anchored" data-anchor-id="memory-spaces"><span class="header-section-number">3.1</span> Memory spaces</h2>
<p>Every object that you create in your Zig source code needs to be stored somewhere, in your computer’s memory. Depending on where and how you define your object, Zig will use a different “memory space”, or a different type of memory to store this object.</p>
<p>Each type of memory normally serves for different purposes. In Zig, there are 3 types of memory (or 3 different memory spaces) that we care about. They are:</p>
<ul>
<li>Global data register (or the “global data section”);</li>
<li>Stack;</li>
<li>Heap;</li>
</ul>
<section id="sec-compile-time" class="level3" data-number="3.1.1">
<h3 data-number="3.1.1" class="anchored" data-anchor-id="sec-compile-time"><span class="header-section-number">3.1.1</span> Compile-time known versus runtime known</h3>
<p>One strategy that Zig uses to decide where it will store each object that you declare, is by looking at the value of this particular object. More specifically, by investigating if this value is known at “compile-time” or at “runtime”.</p>
<p>When you write a program in Zig, the values of some of the objects that you write in your program are <em>known at compile time</em>. Meaning that, when you compile your Zig source code, during the compilation process, the <code>zig</code> compiler can figure out the exact value of a particular object that exists in your source code. Knowing the length (or the size) of each object is also important. So the length (or the size) of each object that you write in your program is, in some cases, <em>known at compile time</em>.</p>
<p>The <code>zig</code> compiler cares more about knowing the length (or the size) of a particular object , than to know its actual value. But, if the <code>zig</code> compiler knows the value of the object, then, it automatically knows the size of this object. Because it can simply calculate the size of the object by looking at the size of the value.</p>
<p>Therefore, the priority for the <code>zig</code> compiler is to discover the size of each object in your source code. If the value of the object in question is known at compile-time, then, the <code>zig</code> compiler automatically knows the size/length of this object. But if the value of this object is not known at compile-time, then, the size of this object is only known at compile-time if, and only if, the type of this object has a known fixed size.</p>
<p>In order for a type to have a known fixed size, this type must have data members whose size is fixed. If this type includes, for example, a variable sized array in it, then, this type does not have a known fixed size. Because this array can have any size at runtime (i.e., it can be an array of 2 elements, or 50 elements, or 1 thousand elements, etc.).</p>
<p>For example, a string object, which internally is an array of constant u8 values (<code>[]const u8</code>) has a variable size. It can be a string object with 100 or 500 characters in it. If we do not know at compile-time, which exact string will be stored inside this string object, then, we cannot calculate the size of this string object at compile-time. So, any type, or any struct declaration that you make, that includes a string data member that does not have an explicit fixed size, makes this type, or this new struct that you are declaring, a type that does not have a known fixed size at compile-time.</p>
<p>In contrast, if the type of this struct that you are declaring, includes a data member that is an array, but this array has a known fixed size, like <code>[60]u8</code> (which declares an array of 60 <code>u8</code> values), then, this type, or, this struct that you are declaring, becomes a type with a known fixed size at compile-time. And because of that, in this case, the <code>zig</code> compiler does not need to know at compile-time the exact value of any object of this type. Since the compiler can find the necessary size to store this object by looking at the size of its type.</p>
<p>Let’s look at an example. In the source code below, we have two constant objects (<code>name</code> and <code>array</code>) declared. Because the values of these particular objects are written down, in the source code itself (<code>"Pedro"</code> and the number sequence from 1 to 4), the <code>zig</code> compiler can easily discover the values of these constant objects (<code>name</code> and <code>array</code>) during the compilation process. This is what “known at compile time” means. It refers to any object that you have in your Zig source code whose value can be identified at compile time.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> input_length(input: []<span class="kw">const</span> <span class="dt">u8</span>) <span class="dt">usize</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> n = input.len;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> n;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> name = <span class="st">"Pedro"</span>;</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> array = [_]<span class="dt">u8</span><span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    _ = name; _ = array;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>The other side of the spectrum are objects whose values are not known at compile time. Function arguments are a classic example of this. Because the value of each function argument depends on the value that you assign to this particular argument, when you call the function.</p>
<p>For example, the function <code>input_length()</code> contains an argument named <code>input</code>, which is an array of constant <code>u8</code> integers (<code>[]const u8</code>). It’s impossible to know the value of this particular argument at compile time. And it also is impossible to know the size/length of this particular argument. Because it’s an array that does not have a fixed size specified explicitly in the argument type annotation.</p>
<p>So, we know that this <code>input</code> argument will be an array of <code>u8</code> integers. But we do not know at compile-time, its value, and neither its size. This information is known only at runtime, which is the period of time when you program is executed. As a consequence, the value of the expression <code>input.len</code> is also known only at runtime. This is an intrinsic characteristic of any function. Just remember that the value of function arguments is usually not “compile-time known”.</p>
<p>However, as I mentioned earlier, what really matters to the compiler is to know the size of the object at compile-time, and not necessarily its value. So, although we don’t know the value of the object <code>n</code>, which is the result of the expression <code>input.len</code>, at compile-time, we do know its size. Because the expression <code>input.len</code> always returns a value of type <code>usize</code>, and the type <code>usize</code> has a known fixed size.</p>
</section>
<section id="global-data-register" class="level3" data-number="3.1.2">
<h3 data-number="3.1.2" class="anchored" data-anchor-id="global-data-register"><span class="header-section-number">3.1.2</span> Global data register</h3>
<p>The global data register is a specific section of the executable of your Zig program, that is responsible for storing any value that is known at compile time.</p>
<p>Every constant object whose value is known at compile time that you declare in your source code, is stored in the global data register. Also, every literal value that you write in your source code, such as the string <code>"this is a string"</code>, or the integer <code>10</code>, or a boolean value such as <code>true</code>, is also stored in the global data register.</p>
<p>Honestly, you don’t need to care much about this memory space. Because you can’t control it, you can’t deliberately access it or use it for your own purposes. Also, this memory space does not affect the logic of your program. It simply exists in your program.</p>
</section>
<section id="stack-vs-heap" class="level3" data-number="3.1.3">
<h3 data-number="3.1.3" class="anchored" data-anchor-id="stack-vs-heap"><span class="header-section-number">3.1.3</span> Stack vs Heap</h3>
<p>If you are familiar with systems programming, or just low-level programming in general, you probably have heard of the “duel” between Stack vs Heap. These are two different types of memory, or different memory spaces, which are both available in Zig.</p>
<p>These two types of memory don’t actually duel with each other. This is a common mistake that beginners have, when seeing “x vs y” styles of tabloid headlines. These two types of memory are actually complementary to each other. So, in almost every Zig program that you ever write, you will likely use a combination of both. I will describe each memory space in detail over the next sections. But for now, I just want to stablish the main difference between these two types of memory.</p>
<p>In essence, the stack memory is normally used to store values whose length is fixed and known at compile time. In contrast, the heap memory is a <em>dynamic</em> type of memory space, meaning that, it’s used to store values whose length might grow during the execution (runtime) of your program <span class="citation" data-cites="jenny2022">(<a href="references.html#ref-jenny2022" role="doc-biblioref">Chen and Guo 2022</a>)</span>.</p>
<p>Lengths that grow during runtime are intrinsically associated with “runtime known” type of values. In other words, if you have an object whose length might grow during runtime, then, the length of this object becomes not known at compile time. If the length is not known at compile-time, the value of this object also becomes not known at compile-time. These types of objects should be stored in the heap memory space, which is a dynamic memory space, which can grow or shrink to fit the size of your objects.</p>
</section>
<section id="sec-stack" class="level3" data-number="3.1.4">
<h3 data-number="3.1.4" class="anchored" data-anchor-id="sec-stack"><span class="header-section-number">3.1.4</span> Stack</h3>
<p>The stack is a type of memory that uses the power of the <em>stack data structure</em>, hence the name. A “stack” is a type of <em>data structure</em> that uses a “last in, first out” (LIFO) mechanism to store the values you give it to. I imagine you are familiar with this data structure. But, if you are not, the <a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)">Wikipedia page</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> , or, the <a href="https://www.geeksforgeeks.org/stack-data-structure/">Geeks For Geeks page</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> are both excellent and easy resources to fully understand how this data structure works.</p>
<p>So, the stack memory space is a type of memory that stores values using a stack data structure. It adds and removes values from the memory by following a “last in, first out” (LIFO) principle.</p>
<p>Every time you make a function call in Zig, an amount of space in the stack is reserved for this particular function call <span class="citation" data-cites="jenny2022 zigdocs">(<a href="references.html#ref-jenny2022" role="doc-biblioref">Chen and Guo 2022</a>; <a href="references.html#ref-zigdocs" role="doc-biblioref">Zig Software Foundation 2024</a>)</span>. The value of each function argument given to the function in this function call is stored in this stack space. Also, every local object that you declare inside the function scope is usually stored in this same stack space.</p>
<p>Looking at the example below, the object <code>result</code> is a local object declared inside the scope of the <code>add()</code> function. Because of that, this object is stored inside the stack space reserved for the <code>add()</code> function. The <code>r</code> object (which is declared outside of the <code>add()</code> function scope) is also stored in the stack. But since it’s declared in the “outer” scope, this object is stored in the stack space that belongs to this outer scope.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x: <span class="dt">u8</span>, y: <span class="dt">u8</span>) <span class="dt">u8</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> result = x + y;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> result;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> r = add(<span class="dv">5</span>, <span class="dv">27</span>);</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    _ = r;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>So, any object that you declare inside the scope of a function is always stored inside the space that was reserved for that particular function in the stack memory. This also counts for any object declared inside the scope of your <code>main()</code> function for example. As you would expect, in this case, they are stored inside the stack space reserved for the <code>main()</code> function.</p>
<p>One very important detail about the stack memory is that <strong>it frees itself automatically</strong>. This is very important, remember that. When objects are stored in the stack memory, you don’t have the work (or the responsibility) of freeing/destroying these objects. Because they will be automatically destroyed once the stack space is freed at the end of the function scope.</p>
<p>So, once the function call returns (or ends, if you prefer to call it this way) the space that was reserved in the stack is destroyed, and all of the objects that were in that space goes away with it. This mechanism exists because this space, and the objects within it, are not necessary anymore, since the function “finished its business”. Using the <code>add()</code> function that we exposed above as an example, it means that the object <code>result</code> is automatically destroyed once the function returns.</p>
<div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Local objects that are stored in the stack space of a function are automatically freed/destroyed at the end of the function scope.</p>
</div>
</div>
<p>This same logic applies to any other special structure in Zig that has its own scope by surrounding it with curly braces (<code>{}</code>). For loops, while loops, if else statements, etc. For example, if you declare any local object in the scope of a for loop, this local object is accessible only within the scope of this particular for loop. Because once the scope of this for loop ends, the space in the stack reserved for this for loop is freed. The example below demonstrates this idea.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This does not compile successfully!</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> a = [_]<span class="dt">u8</span><span class="op">{</span><span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">for</span> (<span class="dv">0</span>..a.len) |i| <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> index = i;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    _ = index;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">// Trying to use an object that was</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="co">// declared in the for loop scope,</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">// and that does not exist anymore.</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>std.debug.print(<span class="st">"{d}</span><span class="sc">\n</span><span class="st">"</span>, .<span class="op">{</span>index<span class="op">}</span>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>One important consequence of this mechanism is that, once the function returns, you can no longer access any memory address that was inside the space in the stack reserved for this particular function. Because this space was destroyed. This means that, if this local object is stored in the stack, you cannot make a function that <strong>returns a pointer to this object</strong>.</p>
<p>Think about that for a second. If all local objects in the stack are destroyed at the end of the function scope, why would you even consider returning a pointer to one of these objects? This pointer is at best, invalid, or, more likely, “undefined”.</p>
<p>In conclusion, it’s totally fine to write a function that returns the local object itself as result, because then, you return the value of that object as the result. But, if this local object is stored in the stack, you should never write a function that returns a pointer to this local object. Because the memory address pointed by the pointer no longer exists.</p>
<p>So, using again the <code>add()</code> function as an example, if you rewrite this function so that it returns a pointer to the local object <code>result</code>, the <code>zig</code> compiler will actually compile your program, with no warnings or errors. At first glance, it looks like this is good code that works as expected. But this is a lie!</p>
<p>If you try to take a look at the value inside of the <code>r</code> object, or, if you try to use this <code>r</code> object in another expression or function call, then, you would have undefined behaviour, and major bugs in your program <span class="citation" data-cites="zigdocs">(<a href="references.html#ref-zigdocs" role="doc-biblioref">Zig Software Foundation 2024</a>, see “Lifetime and Ownership”<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> and “Undefined Behaviour”<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a> sections)</span>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x: <span class="dt">u8</span>, y: <span class="dt">u8</span>) *<span class="kw">const</span> <span class="dt">u8</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> result = x + y;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">return</span> &amp;result;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This code compiles successfully. But it has</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// undefined behaviour. Never do this!!!</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">// The `r` object is undefined!</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> r = add(<span class="dv">5</span>, <span class="dv">27</span>); _ = r;</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>This “invalid pointer to stack variable” problem is well known across many programming language communities. If you try to do the same thing, for example, in a C or C++ program (i.e., returning an address to a local object stored in the stack), you would also get undefined behaviour in the program.</p>
<div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>If a local object in your function is stored in the stack, you should never return a pointer to this local object from the function. Because this pointer will always become undefined after the function returns, since the stack space of the function is destroyed at the end of its scope.</p>
</div>
</div>
<p>But what if you really need to use this local object in some way after your function returns? How can you do this? The answer is: “in the same way you would do if this were a C or C++ program. By returning an address to an object stored in the heap”. The heap memory has a much more flexible lifecycle, and allows you to get a valid pointer to a local object of a function that already returned from its scope.</p>
</section>
<section id="sec-heap" class="level3" data-number="3.1.5">
<h3 data-number="3.1.5" class="anchored" data-anchor-id="sec-heap"><span class="header-section-number">3.1.5</span> Heap</h3>
<p>One important limitation of the stack, is that, only objects whose length/size is known at compile-time can be stored in it. In contrast, the heap is a much more dynamic (and flexible) type of memory. It’s the perfect type of memory to use for objects whose size/length might grow during the execution of your program.</p>
<p>Virtually any application that behaves as a server is a classic use case of the heap. A HTTP server, a SSH server, a DNS server, a LSP server, … any type of server. In summary, a server is a type of application that runs for long periods of time, and that serves (or “deals with”) any incoming request that reaches this particular server.</p>
<p>The heap is a good choice for this type of system, mainly because the server does not know upfront how many requests it will receive from users, while it is active. It could be a single request, 5 thousand requests, or even zero requests. The server needs to have the ability to allocate and manage its memory according to how many requests it receives.</p>
<p>Another key difference between the stack and the heap, is that the heap is a type of memory that you, the programmer, have complete control over. This makes the heap a more flexible type of memory, but it also makes it harder to work with. Because you, the programmer, is responsible for managing everything related to it. Including where the memory is allocated, how much memory is allocated, and where this memory is freed.</p>
<blockquote class="blockquote">
<p>Unlike stack memory, heap memory is allocated explicitly by programmers and it won’t be deallocated until it is explicitly freed <span class="citation" data-cites="jenny2022">(<a href="references.html#ref-jenny2022" role="doc-biblioref">Chen and Guo 2022</a>)</span>.</p>
</blockquote>
<p>To store an object in the heap, you, the programmer, needs to explicitly tells Zig to do so, by using an allocator to allocate some space in the heap. In <a href="#sec-allocators" class="quarto-xref"><span>Section 3.3</span></a>, I will present how you can use allocators to allocate memory in Zig.</p>
<div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Every memory you allocate in the heap needs to be explicitly freed by you, the programmer.</p>
</div>
</div>
<p>The majority of allocators in Zig do allocate memory on the heap. But some exceptions to this rule are <code>ArenaAllocator()</code> and <code>FixedBufferAllocator()</code>. The <code>ArenaAllocator()</code> is a special type of allocator that works in conjunction with a second type of allocator. On the other side, the <code>FixedBufferAllocator()</code> is an allocator that works based on buffer objects created on the stack. This means that the <code>FixedBufferAllocator()</code> makes allocations only on the stack.</p>
</section>
<section id="summary" class="level3" data-number="3.1.6">
<h3 data-number="3.1.6" class="anchored" data-anchor-id="summary"><span class="header-section-number">3.1.6</span> Summary</h3>
<p>After discussing all of these boring details, we can quickly recap what we learned. In summary, the Zig compiler will use the following rules to decide where each object you declare is stored:</p>
<ol type="1">
<li>every literal value (such as <code>"this is string"</code>, <code>10</code>, or <code>true</code>) is stored in the global data section.</li>
<li>every constant object (<code>const</code>) whose value <strong>is known at compile-time</strong> is also stored in the global data section.</li>
<li>every object (constant or not) whose length/size <strong>is known at compile time</strong> is stored in the stack space for the current scope.</li>
<li>if an object is created with the method <code>alloc()</code> or <code>create()</code> of an allocator object, this object is stored in the memory space used by this particular allocator object. Most of allocators available in Zig use the heap memory, so, this object is likely stored in the heap (<code>FixedBufferAllocator()</code> is an exception to that).</li>
<li>the heap can only be accessed through allocators. If your object was not created through the <code>alloc()</code> or <code>create()</code> methods of an allocator object, then, it is most certainly not an object stored in the heap.</li>
</ol>
</section>
</section>
<section id="sec-stack-overflow" class="level2" data-number="3.2">
<h2 data-number="3.2" class="anchored" data-anchor-id="sec-stack-overflow"><span class="header-section-number">3.2</span> Stack overflows</h2>
<p>Allocating memory on the stack is generally faster than allocating it on the heap. But this better performance comes with many restrictions. We have already discussed many of these restrictions of the stack in <a href="#sec-stack" class="quarto-xref"><span>Section 3.1.4</span></a>. But there is one more important limitation that I want to talk about, which is the size of the stack itself.</p>
<p>The stack is limited in size. This size varies from computer to computer, and it depends on a lot of things (the computer architecture, the operating system, etc.). Nevertheless, this size is usually not that big. This is why we normally use the stack to store only temporary and small objects in memory.</p>
<p>In essence, if you try to make an allocation on the stack, that is so big that exceeds the stack size limit, a <em>stack overflow</em> happens, and your program just crashes as a result of that. In other words, a stack overflow happens when you attempt to use more space than is available on the stack.</p>
<p>This type of problem is very similar to a <em>buffer overflow</em>, i.e., you are trying to use more space than is available in the “buffer object”. However, a stack overflow always causes your program to crash, while a buffer overflow does not always cause your program to crash (although it often does).</p>
<p>You can see an example of a stack overflow in the example below. We are trying to allocate a very big array of <code>u64</code> values on the stack. You can see below that this program does not run successfully, because it crashed with a “segmentation fault” error message.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> very_big_alloc: [<span class="dv">1000</span> * <span class="dv">1000</span> * <span class="dv">24</span>]<span class="dt">u64</span> = <span class="cn">undefined</span>;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="bu">@memset</span>(very_big_alloc[<span class="dv">0</span>..], <span class="dv">0</span>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<pre><code>Segmentation fault (core dumped)</code></pre>
<p>This segmentation fault error is a result of the stack overflow that was caused by the big memory allocation made on the stack, to store the <code>very_big_alloc</code> object. This is why very big objects are usually stored on the heap, instead of the stack.</p>
</section>
<section id="sec-allocators" class="level2" data-number="3.3">
<h2 data-number="3.3" class="anchored" data-anchor-id="sec-allocators"><span class="header-section-number">3.3</span> Allocators</h2>
<p>One key aspect about Zig, is that there are “no hidden-memory allocations” in Zig. What that really means, is that “no allocations happen behind your back in the standard library” <span class="citation" data-cites="zigguide">(<a href="references.html#ref-zigguide" role="doc-biblioref">Sobeston 2024</a>)</span>.</p>
<p>This is a known problem, especially in C++. Because in C++, there are some operators that do allocate memory behind the scene, and there is no way for you to know that, until you actually read the source code of these operators, and find the memory allocation calls. Many programmers find this behaviour annoying and hard to keep track of.</p>
<p>But, in Zig, if a function, an operator, or anything from the standard library needs to allocate some memory during its execution, then, this function/operator needs to receive (as input) an allocator provided by the user, to actually be able to allocate the memory it needs.</p>
<p>This creates a clear distinction between functions that “do not” from those that “actually do” allocate memory. Just look at the arguments of this function. If a function, or operator, has an allocator object as one of its inputs/arguments, then, you know for sure that this function/operator will allocate some memory during its execution.</p>
<p>An example is the <code>allocPrint()</code> function from the Zig Standard Library. With this function, you can write a new string using format specifiers. So, this function is, for example, very similar to the function <code>sprintf()</code> in C. In order to write such a new string, the <code>allocPrint()</code> function needs to allocate some memory to store the output string.</p>
<p>That is why, the first argument of this function is an allocator object that you, the user/programmer, gives as input to the function. In the example below, I am using the <code>GeneralPurposeAllocator()</code> as my allocator object. But I could easily use any other type of allocator object from the Zig Standard Library.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> gpa = std.heap.GeneralPurposeAllocator(.<span class="op">{}</span>)<span class="op">{}</span>;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> allocator = gpa.allocator();</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> name = <span class="st">"Pedro"</span>;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> output = <span class="kw">try</span> std.fmt.allocPrint(</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    allocator,</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">"Hello {s}!!!"</span>,</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    .<span class="op">{</span>name<span class="op">}</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">try</span> stdout.print(<span class="st">"{s}</span><span class="sc">\n</span><span class="st">"</span>, .<span class="op">{</span>output<span class="op">}</span>);</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="kw">try</span> stdout.flush();</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Hello Pedro!!!</code></pre>
</div>
</div>
<p>You get a lot of control over where and how much memory this function can allocate. Because it is you, the user/programmer, that provides the allocator for the function to use. This makes “total control” over memory management easier to achieve in Zig.</p>
<section id="what-are-allocators" class="level3" data-number="3.3.1">
<h3 data-number="3.3.1" class="anchored" data-anchor-id="what-are-allocators"><span class="header-section-number">3.3.1</span> What are allocators?</h3>
<p>Allocators in Zig are objects that you can use to allocate memory for your program. They are similar to the memory allocating functions in C, like <code>malloc()</code> and <code>calloc()</code>. So, if you need to use more memory than you initially have, during the execution of your program, you can simply ask for more memory by using an allocator object.</p>
<p>Zig offers different types of allocators, and they are usually available through the <code>std.heap</code> module of the standard library. Thus, just import the Zig Standard Library into your Zig module (with <code>@import("std")</code>), and you can start using these allocators in your code.</p>
<p>Furthermore, every allocator object is built on top of the <code>Allocator</code> interface in Zig. This means that, every allocator object you find in Zig must have the methods <code>alloc()</code>, <code>create()</code>, <code>free()</code> and <code>destroy()</code>. So, you can change the type of allocator you are using, but you don’t need to change the function calls to the methods that do the memory allocation (and the free memory operations) for your program.</p>
</section>
<section id="why-you-need-an-allocator" class="level3" data-number="3.3.2">
<h3 data-number="3.3.2" class="anchored" data-anchor-id="why-you-need-an-allocator"><span class="header-section-number">3.3.2</span> Why you need an allocator?</h3>
<p>As we described in <a href="#sec-stack" class="quarto-xref"><span>Section 3.1.4</span></a>, everytime you make a function call in Zig, a space in the stack is reserved for this function call. But the stack has a key limitation which is: every object stored in the stack has a known fixed length.</p>
<p>But in reality, there are two very common instances where this “fixed length limitation” of the stack is a deal braker:</p>
<ol type="1">
<li>the objects that you create inside your function might grow in size during the execution of the function.</li>
<li>sometimes, it’s impossible to know upfront how many inputs you will receive, or how big this input will be.</li>
</ol>
<p>Also, there is another instance where you might want to use an allocator, which is when you want to write a function that returns a pointer to a local object. As I described in <a href="#sec-stack" class="quarto-xref"><span>Section 3.1.4</span></a>, you cannot do that if this local object is stored in the stack. However, if this object is stored in the heap, then, you can return a pointer to this object at the end of the function. Because you (the programmer) control the lifetime of any heap memory that you allocate. You decide when this memory gets destroyed/freed.</p>
<p>These are common situations for which the stack is not good. That is why you need a different memory management strategy to store these objects inside your function. You need to use a memory type that can grow together with your objects, or that you can control the lifetime of this memory. The heap fits this description.</p>
<p>Allocating memory on the heap is commonly known as dynamic memory management. As the objects you create grow in size during the execution of your program, you grow the amount of memory you have by allocating more memory in the heap to store these objects. And you do that in Zig, by using an allocator object.</p>
</section>
<section id="the-different-types-of-allocators" class="level3" data-number="3.3.3">
<h3 data-number="3.3.3" class="anchored" data-anchor-id="the-different-types-of-allocators"><span class="header-section-number">3.3.3</span> The different types of allocators</h3>
<p>At the moment of the writing of this book, in Zig, we have 6 different allocators available in the standard library:</p>
<ul>
<li><code>GeneralPurposeAllocator()</code>.</li>
<li><code>page_allocator()</code>.</li>
<li><code>FixedBufferAllocator()</code> and <code>ThreadSafeFixedBufferAllocator()</code>.</li>
<li><code>ArenaAllocator()</code>.</li>
<li><code>c_allocator()</code> (requires you to link to libc).</li>
</ul>
<p>Each allocator has its own perks and limitations. All allocators, except <code>FixedBufferAllocator()</code> and <code>ArenaAllocator()</code>, are allocators that use the heap memory. So any memory that you allocate with these allocators, will be placed in the heap.</p>
</section>
<section id="general-purpose-allocators" class="level3" data-number="3.3.4">
<h3 data-number="3.3.4" class="anchored" data-anchor-id="general-purpose-allocators"><span class="header-section-number">3.3.4</span> General-purpose allocators</h3>
<p>The <code>GeneralPurposeAllocator()</code>, as the name suggests, is a “general purpose” allocator. You can use it for every type of task. In the example below, I’m allocating enough space to store a single integer in the object <code>some_number</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb9"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> gpa = std.heap.GeneralPurposeAllocator(.<span class="op">{}</span>)<span class="op">{}</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> allocator = gpa.allocator();</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> some_number = <span class="kw">try</span> allocator.create(<span class="dt">u32</span>);</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> allocator.destroy(some_number);</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    some_number.* = <span class="bu">@as</span>(<span class="dt">u32</span>, <span class="dv">45</span>);</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>While useful, you might want to use the <code>c_allocator()</code>, which is a alias to the C standard allocator <code>malloc()</code>. So, yes, you can use <code>malloc()</code> in Zig if you want to. Just use the <code>c_allocator()</code> from the Zig standard library. However, if you do use <code>c_allocator()</code>, you must link to Libc when compiling your source code with the <code>zig</code> compiler, by including the flag <code>-lc</code> in your compilation process. If you do not link your source code to Libc, Zig will not be able to find the <code>malloc()</code> implementation in your system.</p>
</section>
<section id="page-allocator" class="level3" data-number="3.3.5">
<h3 data-number="3.3.5" class="anchored" data-anchor-id="page-allocator"><span class="header-section-number">3.3.5</span> Page allocator</h3>
<p>The <code>page_allocator()</code> is an allocator that allocates full pages of memory in the heap. In other words, every time you allocate memory with <code>page_allocator()</code>, a full page of memory in the heap is allocated, instead of just a small piece of it.</p>
<p>The size of this page depends on the system you are using. Most systems use a page size of 4KB in the heap, so, that is the amount of memory that is normally allocated in each call by <code>page_allocator()</code>. That is why, <code>page_allocator()</code> is considered a fast, but also “wasteful” allocator in Zig. Because it allocates a big amount of memory in each call, and you most likely will not need that much memory in your program.</p>
</section>
<section id="buffer-allocators" class="level3" data-number="3.3.6">
<h3 data-number="3.3.6" class="anchored" data-anchor-id="buffer-allocators"><span class="header-section-number">3.3.6</span> Buffer allocators</h3>
<p>The <code>FixedBufferAllocator()</code> and <code>ThreadSafeFixedBufferAllocator()</code> are allocator objects that work with a fixed sized buffer object at the back. In other words, they use a fixed sized buffer object as the basis for the memory. When you ask these allocator objects to allocate some memory for you, they are essentially reserving some amount of space inside this fixed sized buffer object for you to use.</p>
<p>This means that, in order to use these allocators, you must first create a buffer object in your code, and then, give this buffer object as an input to these allocators.</p>
<p>This also means that, these allocator objects can allocate memory both in the stack or in the heap. Everything depends on where the buffer object that you provide lives. If this buffer object lives in the stack, then, the memory allocated is “stack-based”. But if it lives on the heap, then, the memory allocated is “heap-based”.</p>
<p>In the example below, I’m creating a <code>buffer</code> object on the stack that is 10 elements long. Notice that I give this <code>buffer</code> object to the <code>FixedBufferAllocator()</code> constructor. Now, because this <code>buffer</code> object is 10 elements long, this means that I am limited to this space. I cannot allocate more than 10 elements with this allocator object. If I try to allocate more than that, the <code>alloc()</code> method will return an <code>OutOfMemory</code> error value.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb10"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> buffer: [<span class="dv">10</span>]<span class="dt">u8</span> = <span class="cn">undefined</span>;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">for</span> (<span class="dv">0</span>..buffer.len) |i| <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    buffer[i] = <span class="dv">0</span>; <span class="co">// Initialize to zero</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> fba = std.heap.FixedBufferAllocator.init(&amp;buffer);</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> allocator = fba.allocator();</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> input = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">5</span>);</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">defer</span> allocator.free(input);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Remember, the memory allocated by these allocator objects can be either from the stack, or, from the heap. It all depends on where the buffer object that you provide lives. In the above example, the <code>buffer</code> object lives in the stack, and, therefore, the memory allocated is based in the stack. But what if it was based on the heap?</p>
<p>As we described in <a href="#sec-stack-overflow" class="quarto-xref"><span>Section 3.2</span></a>, one of the main reasons why you would use the heap, instead of the stack, is to allocate huge amounts of space to store very big objects. Thus, let’s suppose you wanted to use a very big buffer object as the basis for your allocator objects. You would have to allocate this very big buffer object on the heap. The example below demonstrates this case.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb11"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> heap = std.heap.page_allocator;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> memory_buffer = <span class="kw">try</span> heap.alloc(</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">u8</span>, <span class="dv">100</span> * <span class="dv">1024</span> * <span class="dv">1024</span> <span class="co">// 100 MB memory</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">defer</span> heap.free(memory_buffer);</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> fba = std.heap.FixedBufferAllocator.init(</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    memory_buffer</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>);</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> allocator = fba.allocator();</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> input = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">1000</span>);</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="kw">defer</span> allocator.free(input);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="sec-arena-allocator" class="level3" data-number="3.3.7">
<h3 data-number="3.3.7" class="anchored" data-anchor-id="sec-arena-allocator"><span class="header-section-number">3.3.7</span> Arena allocator</h3>
<p>The <code>ArenaAllocator()</code> is an allocator object that takes a child allocator as input. The idea behind the <code>ArenaAllocator()</code> in Zig is similar to the concept of “arenas” in the programming language Go<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>. It’s an allocator object that allows you to allocate memory as many times you want, but free all memory only once. In other words, if you have, for example, called 5 times the method <code>alloc()</code> of an <code>ArenaAllocator()</code> object, you can free all the memory you allocated over these 5 calls at once, by simply calling the <code>deinit()</code> method of the same <code>ArenaAllocator()</code> object.</p>
<p>If you give, for example, a <code>GeneralPurposeAllocator()</code> object as input to the <code>ArenaAllocator()</code> constructor, like in the example below, then, the allocations you perform with <code>alloc()</code> will actually be made with the underlying object <code>GeneralPurposeAllocator()</code> that was passed. So, with an arena allocator, any new memory you ask for is allocated by the child allocator. The only thing that an arena allocator really does is help you to free all the memory you allocated multiple times with just a single command. In the example below, I called <code>alloc()</code> 3 times. So, if I did not use an arena allocator, then, I would need to call <code>free()</code> 3 times to free all the allocated memory.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb12"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> gpa = std.heap.GeneralPurposeAllocator(.<span class="op">{}</span>)<span class="op">{}</span>;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> aa = std.heap.ArenaAllocator.init(gpa.allocator());</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">defer</span> aa.deinit();</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> allocator = aa.allocator();</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> in1 = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">5</span>);</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> in2 = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">10</span>);</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> in3 = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">15</span>);</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>_ = in1; _ = in2; _ = in3;</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="the-alloc-and-free-methods" class="level3" data-number="3.3.8">
<h3 data-number="3.3.8" class="anchored" data-anchor-id="the-alloc-and-free-methods"><span class="header-section-number">3.3.8</span> The <code>alloc()</code> and <code>free()</code> methods</h3>
<p>In the code example below, we are accessing the <code>stdin</code>, which is the standard input channel, to receive an input from the user. We read the next line of input given by the user with the <code>takeDelimiterExclusive()</code> method.</p>
<p>Now, after reading the input of the user, we need to store this input somewhere in our program. That is why I use an allocator in this example. I use it to allocate some amount of memory to store this input given by the user. More specifically, the method <code>alloc()</code> of the allocator object is used to allocate an array capable of storing 50 <code>u8</code> values.</p>
<p>Notice that this <code>alloc()</code> method receives two inputs. The first one, is a type. This defines what type of values the allocated array will store. In the example below, we are allocating an array of unsigned 8-bit integers (<code>u8</code>). But you can create an array to store any type of value you want. Next, in the second argument, we define the size of the allocated array, by specifying how many elements this array will contain. In the case below, we are allocating an array of 50 elements.</p>
<p>In <a href="01-zig-weird.html#sec-zig-strings" class="quarto-xref"><span>Section 1.8</span></a> we described that strings in Zig are simply arrays of characters. Each character is represented by a <code>u8</code> value<a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a>. So, this means that the array that was allocated in the object <code>input</code> is capable of storing a string that is 50-characters long.</p>
<p>So, in essence, the expression <code>var input: [50]u8 = undefined</code> would create an array for 50 <code>u8</code> values in the stack of the current scope. But, you can allocate the same array in the heap by using the expression <code>var input = try allocator.alloc(u8, 50)</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> io = std.testing.io;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> stdin_buffer: [<span class="dv">1024</span>]<span class="dt">u8</span> = <span class="cn">undefined</span>;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> stdin_reader = std.fs.File.stdin().reader(io, &amp;stdin_buffer);</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> stdin = &amp;stdin_reader.interface;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> gpa = std.heap.GeneralPurposeAllocator(.<span class="op">{}</span>)<span class="op">{}</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> allocator = gpa.allocator();</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> input = <span class="kw">try</span> allocator.alloc(<span class="dt">u8</span>, <span class="dv">50</span>);</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> allocator.free(input);</span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="bu">@memset</span>(input[<span class="dv">0</span>..], <span class="dv">0</span>);</span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Read user input until a line break is found.</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> stream = <span class="kw">try</span> stdin.takeDelimiterExclusive(<span class="ch">'\n'</span>);</span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Store the input into our heap memory.</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    <span class="bu">@memcpy</span>(input[<span class="dv">0</span>..stream.len], stream[<span class="dv">0</span>..]);</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Print our heap memory, so that we can see what</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// was stored in it.</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    std.debug.print(<span class="st">"{s}</span><span class="sc">\n</span><span class="st">"</span>, .<span class="op">{</span>input<span class="op">}</span>);</span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Also, notice that in this example, we use the <code>defer</code> keyword (which I described in <a href="03-structs.html#sec-defer" class="quarto-xref"><span>Section 2.1.3</span></a>) to run a small piece of code at the end of the current scope, which is the expression <code>allocator.free(input)</code>. When you execute this expression, the allocator will free the memory that it allocated for the <code>input</code> object.</p>
<p>We have talked about this in <a href="#sec-heap" class="quarto-xref"><span>Section 3.1.5</span></a>. You <strong>should always</strong> explicitly free any memory that you allocate using an allocator! You do that by using the <code>free()</code> method of the same allocator object you used to allocate this memory. The <code>defer</code> keyword is used in this example only to help us execute this free operation at the end of the current scope.</p>
</section>
<section id="the-create-and-destroy-methods" class="level3" data-number="3.3.9">
<h3 data-number="3.3.9" class="anchored" data-anchor-id="the-create-and-destroy-methods"><span class="header-section-number">3.3.9</span> The <code>create()</code> and <code>destroy()</code> methods</h3>
<p>With the <code>alloc()</code> and <code>free()</code> methods, you can allocate memory to store multiple elements at once. In other words, with these methods, we always allocate an array to store multiple elements at once. But what if you need enough space to store just a single item? Should you allocate an array of a single element through <code>alloc()</code>?</p>
<p>The answer is no! In this case, you should use the <code>create()</code> method of the allocator object. Every allocator object offers the <code>create()</code> and <code>destroy()</code> methods, which are used to allocate and free memory for a single item, respectively.</p>
<p>So, in essence, if you want to allocate memory to store an array of elements, you should use <code>alloc()</code> and <code>free()</code>. But if you need to store just a single item, then, the <code>create()</code> and <code>destroy()</code> methods are ideal for you.</p>
<p>In the example below, I’m defining a struct to represent an user of some sort. It could be a user for a game, or software to manage resources, it doesn’t matter. Notice that I use the <code>create()</code> method this time, to store a single <code>User</code> object in the program. Also notice that I use the <code>destroy()</code> method to free the memory used by this object at the end of the scope.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> User = <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    id: <span class="dt">usize</span>,</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    name: []<span class="kw">const</span> <span class="dt">u8</span>,</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">pub</span> <span class="kw">fn</span> init(id: <span class="dt">usize</span>, name: []<span class="kw">const</span> <span class="dt">u8</span>) User <span class="op">{</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">return</span> .<span class="op">{</span> .id = id, .name = name <span class="op">}</span>;</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> main() !<span class="dt">void</span> <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">var</span> gpa = std.heap.GeneralPurposeAllocator(.<span class="op">{}</span>)<span class="op">{}</span>;</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> allocator = gpa.allocator();</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> user = <span class="kw">try</span> allocator.create(User);</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">defer</span> allocator.destroy(user);</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>    user.* = User.init(<span class="dv">0</span>, <span class="st">"Pedro"</span>);</span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>


<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0" role="list" style="display: none">
<div id="ref-jenny2022" class="csl-entry" role="listitem">
Chen, Jenny, and Ruohao Guo. 2022. <span>“Stack and Heap Memory.”</span> <em>Introduction to Data Structures and Algorithms with C++</em>. <a href="https://courses.engr.illinois.edu/cs225/fa2022/resources/stack-heap/">https://courses.engr.illinois.edu/cs225/fa2022/resources/stack-heap/</a>.
</div>
<div id="ref-zigguide" class="csl-entry" role="listitem">
Sobeston. 2024. <span>“Zig Guide.”</span> <a href="https://zig.guide/">https://zig.guide/</a>.
</div>
<div id="ref-zigdocs" class="csl-entry" role="listitem">
Zig Software Foundation. 2024. <span>“Language Reference.”</span> Zig Software Foundation. <a href="https://ziglang.org/documentation/master/">https://ziglang.org/documentation/master/</a>.
</div>
</div>
</section>
</section>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr>
<ol>
<li id="fn1"><p><a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)" class="uri">https://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p><a href="https://www.geeksforgeeks.org/stack-data-structure/" class="uri">https://www.geeksforgeeks.org/stack-data-structure/</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p><a href="https://ziglang.org/documentation/master/#Lifetime-and-Ownership" class="uri">https://ziglang.org/documentation/master/#Lifetime-and-Ownership</a><a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><p><a href="https://ziglang.org/documentation/master/#Undefined-Behavior" class="uri">https://ziglang.org/documentation/master/#Undefined-Behavior</a><a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5"><p><a href="https://go.dev/src/arena/arena.go" class="uri">https://go.dev/src/arena/arena.go</a><a href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6"><p>Just remember that this is an oversimplification. If we are talking only about ASCII strings, then yes, every <code>u8</code> value represents a separate character in the string. But if we enter the realm of UTF-8 encoded string, then, this scenario is not always true.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>

</main> <!-- /main -->
<script id="quarto-html-after-body" type="application/javascript">
  window.document.addEventListener("DOMContentLoaded", function (event) {
    // Ensure there is a toggle, if there isn't float one in the top right
    if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
      const a = window.document.createElement('a');
      a.classList.add('top-right');
      a.classList.add('quarto-color-scheme-toggle');
      a.href = "";
      a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
      const i = window.document.createElement("i");
      i.classList.add('bi');
      a.appendChild(i);
      window.document.body.appendChild(a);
    }
    setColorSchemeToggle(hasAlternateSentinel())
    const icon = "";
    const anchorJS = new window.AnchorJS();
    anchorJS.options = {
      placement: 'right',
      icon: icon
    };
    anchorJS.add('.anchored');
    const isCodeAnnotation = (el) => {
      for (const clz of el.classList) {
        if (clz.startsWith('code-annotation-')) {                     
          return true;
        }
      }
      return false;
    }
    const onCopySuccess = function(e) {
      // button target
      const button = e.trigger;
      // don't keep focus
      button.blur();
      // flash "checked"
      button.classList.add('code-copy-button-checked');
      var currentTitle = button.getAttribute("title");
      button.setAttribute("title", "Copied!");
      let tooltip;
      if (window.bootstrap) {
        button.setAttribute("data-bs-toggle", "tooltip");
        button.setAttribute("data-bs-placement", "left");
        button.setAttribute("data-bs-title", "Copied!");
        tooltip = new bootstrap.Tooltip(button, 
          { trigger: "manual", 
            customClass: "code-copy-button-tooltip",
            offset: [0, -8]});
        tooltip.show();    
      }
      setTimeout(function() {
        if (tooltip) {
          tooltip.hide();
          button.removeAttribute("data-bs-title");
          button.removeAttribute("data-bs-toggle");
          button.removeAttribute("data-bs-placement");
        }
        button.setAttribute("title", currentTitle);
        button.classList.remove('code-copy-button-checked');
      }, 1000);
      // clear code selection
      e.clearSelection();
    }
    const getTextToCopy = function(trigger) {
        const codeEl = trigger.previousElementSibling.cloneNode(true);
        for (const childEl of codeEl.children) {
          if (isCodeAnnotation(childEl)) {
            childEl.remove();
          }
        }
        return codeEl.innerText;
    }
    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
      text: getTextToCopy
    });
    clipboard.on('success', onCopySuccess);
    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
        text: getTextToCopy,
        container: window.document.getElementById('quarto-embedded-source-code-modal')
      });
      clipboardModal.on('success', onCopySuccess);
    }
      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
      var mailtoRegex = new RegExp(/^mailto:/);
        var filterRegex = new RegExp('/' + window.location.host + '/');
      var isInternal = (href) => {
          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
      }
      // Inspect non-navigation links and adorn them if external
     var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
      for (var i=0; i<links.length; i++) {
        const link = links[i];
        if (!isInternal(link.href)) {
          // undo the damage that might have been done by quarto-nav.js in the case of
          // links that we want to consider external
          if (link.dataset.originalHref !== undefined) {
            link.href = link.dataset.originalHref;
          }
        }
      }
    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
      const config = {
        allowHTML: true,
        maxWidth: 500,
        delay: 100,
        arrow: false,
        appendTo: function(el) {
            return el.parentElement;
        },
        interactive: true,
        interactiveBorder: 10,
        theme: 'quarto',
        placement: 'bottom-start',
      };
      if (contentFn) {
        config.content = contentFn;
      }
      if (onTriggerFn) {
        config.onTrigger = onTriggerFn;
      }
      if (onUntriggerFn) {
        config.onUntrigger = onUntriggerFn;
      }
      window.tippy(el, config); 
    }
    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
    for (var i=0; i<noterefs.length; i++) {
      const ref = noterefs[i];
      tippyHover(ref, function() {
        // use id or data attribute instead here
        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
        try { href = new URL(href).hash; } catch {}
        const id = href.replace(/^#\/?/, "");
        const note = window.document.getElementById(id);
        if (note) {
          return note.innerHTML;
        } else {
          return "";
        }
      });
    }
    const xrefs = window.document.querySelectorAll('a.quarto-xref');
    const processXRef = (id, note) => {
      // Strip column container classes
      const stripColumnClz = (el) => {
        el.classList.remove("page-full", "page-columns");
        if (el.children) {
          for (const child of el.children) {
            stripColumnClz(child);
          }
        }
      }
      stripColumnClz(note)
      if (id === null || id.startsWith('sec-')) {
        // Special case sections, only their first couple elements
        const container = document.createElement("div");
        if (note.children && note.children.length > 2) {
          container.appendChild(note.children[0].cloneNode(true));
          for (let i = 1; i < note.children.length; i++) {
            const child = note.children[i];
            if (child.tagName === "P" && child.innerText === "") {
              continue;
            } else {
              container.appendChild(child.cloneNode(true));
              break;
            }
          }
          if (window.Quarto?.typesetMath) {
            window.Quarto.typesetMath(container);
          }
          return container.innerHTML
        } else {
          if (window.Quarto?.typesetMath) {
            window.Quarto.typesetMath(note);
          }
          return note.innerHTML;
        }
      } else {
        // Remove any anchor links if they are present
        const anchorLink = note.querySelector('a.anchorjs-link');
        if (anchorLink) {
          anchorLink.remove();
        }
        if (window.Quarto?.typesetMath) {
          window.Quarto.typesetMath(note);
        }
        if (note.classList.contains("callout")) {
          return note.outerHTML;
        } else {
          return note.innerHTML;
        }
      }
    }
    for (var i=0; i<xrefs.length; i++) {
      const xref = xrefs[i];
      tippyHover(xref, undefined, function(instance) {
        instance.disable();
        let url = xref.getAttribute('href');
        let hash = undefined; 
        if (url.startsWith('#')) {
          hash = url;
        } else {
          try { hash = new URL(url).hash; } catch {}
        }
        if (hash) {
          const id = hash.replace(/^#\/?/, "");
          const note = window.document.getElementById(id);
          if (note !== null) {
            try {
              const html = processXRef(id, note.cloneNode(true));
              instance.setContent(html);
            } finally {
              instance.enable();
              instance.show();
            }
          } else {
            // See if we can fetch this
            fetch(url.split('#')[0])
            .then(res => res.text())
            .then(html => {
              const parser = new DOMParser();
              const htmlDoc = parser.parseFromString(html, "text/html");
              const note = htmlDoc.getElementById(id);
              if (note !== null) {
                const html = processXRef(id, note);
                instance.setContent(html);
              } 
            }).finally(() => {
              instance.enable();
              instance.show();
            });
          }
        } else {
          // See if we can fetch a full url (with no hash to target)
          // This is a special case and we should probably do some content thinning / targeting
          fetch(url)
          .then(res => res.text())
          .then(html => {
            const parser = new DOMParser();
            const htmlDoc = parser.parseFromString(html, "text/html");
            const note = htmlDoc.querySelector('main.content');
            if (note !== null) {
              // This should only happen for chapter cross references
              // (since there is no id in the URL)
              // remove the first header
              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
                note.children[0].remove();
              }
              const html = processXRef(null, note);
              instance.setContent(html);
            } 
          }).finally(() => {
            instance.enable();
            instance.show();
          });
        }
      }, function(instance) {
      });
    }
        let selectedAnnoteEl;
        const selectorForAnnotation = ( cell, annotation) => {
          let cellAttr = 'data-code-cell="' + cell + '"';
          let lineAttr = 'data-code-annotation="' +  annotation + '"';
          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
          return selector;
        }
        const selectCodeLines = (annoteEl) => {
          const doc = window.document;
          const targetCell = annoteEl.getAttribute("data-target-cell");
          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
          const lineIds = lines.map((line) => {
            return targetCell + "-" + line;
          })
          let top = null;
          let height = null;
          let parent = null;
          if (lineIds.length > 0) {
              //compute the position of the single el (top and bottom and make a div)
              const el = window.document.getElementById(lineIds[0]);
              top = el.offsetTop;
              height = el.offsetHeight;
              parent = el.parentElement.parentElement;
            if (lineIds.length > 1) {
              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
              height = bottom - top;
            }
            if (top !== null && height !== null && parent !== null) {
              // cook up a div (if necessary) and position it 
              let div = window.document.getElementById("code-annotation-line-highlight");
              if (div === null) {
                div = window.document.createElement("div");
                div.setAttribute("id", "code-annotation-line-highlight");
                div.style.position = 'absolute';
                parent.appendChild(div);
              }
              div.style.top = top - 2 + "px";
              div.style.height = height + 4 + "px";
              div.style.left = 0;
              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
              if (gutterDiv === null) {
                gutterDiv = window.document.createElement("div");
                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
                gutterDiv.style.position = 'absolute';
                const codeCell = window.document.getElementById(targetCell);
                const gutter = codeCell.querySelector('.code-annotation-gutter');
                gutter.appendChild(gutterDiv);
              }
              gutterDiv.style.top = top - 2 + "px";
              gutterDiv.style.height = height + 4 + "px";
            }
            selectedAnnoteEl = annoteEl;
          }
        };
        const unselectCodeLines = () => {
          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
          elementsIds.forEach((elId) => {
            const div = window.document.getElementById(elId);
            if (div) {
              div.remove();
            }
          });
          selectedAnnoteEl = undefined;
        };
          // Handle positioning of the toggle
      window.addEventListener(
        "resize",
        throttle(() => {
          elRect = undefined;
          if (selectedAnnoteEl) {
            selectCodeLines(selectedAnnoteEl);
          }
        }, 10)
      );
      function throttle(fn, ms) {
      let throttle = false;
      let timer;
        return (...args) => {
          if(!throttle) { // first call gets through
              fn.apply(this, args);
              throttle = true;
          } else { // all the others get throttled
              if(timer) clearTimeout(timer); // cancel #2
              timer = setTimeout(() => {
                fn.apply(this, args);
                timer = throttle = false;
              }, ms);
          }
        };
      }
        // Attach click handler to the DT
        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
        for (const annoteDlNode of annoteDls) {
          annoteDlNode.addEventListener('click', (event) => {
            const clickedEl = event.target;
            if (clickedEl !== selectedAnnoteEl) {
              unselectCodeLines();
              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
              if (activeEl) {
                activeEl.classList.remove('code-annotation-active');
              }
              selectCodeLines(clickedEl);
              clickedEl.classList.add('code-annotation-active');
            } else {
              // Unselect the line
              unselectCodeLines();
              clickedEl.classList.remove('code-annotation-active');
            }
          });
        }
    const findCites = (el) => {
      const parentEl = el.parentElement;
      if (parentEl) {
        const cites = parentEl.dataset.cites;
        if (cites) {
          return {
            el,
            cites: cites.split(' ')
          };
        } else {
          return findCites(el.parentElement)
        }
      } else {
        return undefined;
      }
    };
    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
    for (var i=0; i<bibliorefs.length; i++) {
      const ref = bibliorefs[i];
      const citeInfo = findCites(ref);
      if (citeInfo) {
        tippyHover(citeInfo.el, function() {
          var popup = window.document.createElement('div');
          citeInfo.cites.forEach(function(cite) {
            var citeDiv = window.document.createElement('div');
            citeDiv.classList.add('hanging-indent');
            citeDiv.classList.add('csl-entry');
            var biblioDiv = window.document.getElementById('ref-' + cite);
            if (biblioDiv) {
              citeDiv.innerHTML = biblioDiv.innerHTML;
            }
            popup.appendChild(citeDiv);
          });
          return popup.innerHTML;
        });
      }
    }
  });
  </script>
<nav class="page-navigation">
  <div class="nav-page nav-page-previous">
      <a href="../Chapters/03-structs.html" class="pagination-link" aria-label="Control flow, structs, modules and types">
        <i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><span class="chapter-number">2</span>&nbsp; <span class="chapter-title">Control flow, structs, modules and types</span></span>
      </a>          
  </div>
  <div class="nav-page nav-page-next">
      <a href="../Chapters/01-base64.html" class="pagination-link" aria-label="Project 1 - Building a base64 encoder/decoder">
        <span class="nav-page-text"><span class="chapter-number">4</span>&nbsp; <span class="chapter-title">Project 1 - Building a base64 encoder/decoder</span></span> <i class="bi bi-arrow-right-short"></i>
      </a>
  </div>
</nav>
</div> <!-- /content -->




</body></html>